import * as THREE from 'three';
import { Vec3 } from '@/core/types';
import { EntityType, EntityData, BoundingBox, AIBehavior, EntityStats, AIState } from './types';
import { WorldManager } from '@/world/WorldManager';
import { ItemDropManager } from '@/world/ItemDrop';

export abstract class Entity {
  protected id: string;
  protected type: EntityType;
  protected position: Vec3;
  protected velocity: Vec3;
  protected rotation: number;
  protected health: number;
  protected maxHealth: number;
  protected onGround: boolean;
  protected age: number;
  protected mesh?: THREE.Object3D;
  protected worldManager: WorldManager;
  protected stats: EntityStats;
  protected ai?: AIBehavior;
  protected lastUpdate: number;
  protected itemDropManager?: ItemDropManager;

  constructor(id: string, type: EntityType, position: Vec3, worldManager: WorldManager, stats: EntityStats, itemDropManager?: ItemDropManager) {
    this.id = id;
    this.type = type;
    this.position = { ...position };
    this.velocity = { x: 0, y: 0, z: 0 };
    this.rotation = 0;
    this.health = stats.maxHealth;
    this.maxHealth = stats.maxHealth;
    this.onGround = false;
    this.age = 0;
    this.worldManager = worldManager;
    this.stats = stats;
    this.itemDropManager = itemDropManager;
    this.lastUpdate = Date.now();
    
    this.initializeAI();
    this.createMesh();
  }

  protected abstract initializeAI(): void;
  protected abstract createMesh(): void;

  public update(deltaTime: number): void {
    this.age += deltaTime;
    this.lastUpdate = Date.now();
    
    // 更新AI
    if (this.ai) {
      this.updateAI(deltaTime);
    }
    
    // 应用物理
    this.applyPhysics(deltaTime);
    
    // 更新网格位置
    this.updateMeshPosition();
    
    // 检查健康状态
    if (this.health <= 0 && this.ai?.state !== AIState.DEAD) {
      this.die();
    }
  }

  protected updateAI(deltaTime: number): void {
    if (!this.ai) return;
    
    this.ai.stateTimer += deltaTime;
    
    // 子类实现具体的AI逻辑
    this.processAI(deltaTime);
  }

  protected abstract processAI(deltaTime: number): void;

  protected applyPhysics(deltaTime: number): void {
    const gravity = -9.8;
    
    // 只有在不在地面上时才应用重力
    if (!this.onGround) {
      this.velocity.y += gravity * deltaTime;
    }
    
    // 检查方块碰撞
    const newPosition = this.checkBlockCollision(deltaTime);
    this.position = newPosition;
    
    // 应用摩擦力（只在地面上时应用）
    if (this.onGround) {
      this.velocity.x *= 0.8;
      this.velocity.z *= 0.8;
    }
  }

  private checkBlockCollision(deltaTime: number): Vec3 {
    const newPosition = { ...this.position };
    const halfWidth = this.stats.size.width / 2;
    const height = this.stats.size.height;
    
    // X轴碰撞检测
    newPosition.x += this.velocity.x * deltaTime;
    if (this.isCollidingWithBlocks(newPosition, halfWidth, height)) {
      newPosition.x = this.position.x;
      this.velocity.x = 0;
    }
    
    // Y轴碰撞检测
    newPosition.y += this.velocity.y * deltaTime;
    
    // 检查是否在地面上（检查脚下是否有方块）
    const groundCheckPos = { ...newPosition, y: newPosition.y - 0.1 };
    const hasGroundBelow = this.isCollidingWithBlocks(groundCheckPos, halfWidth, 0.1);
    
    if (this.isCollidingWithBlocks(newPosition, halfWidth, height)) {
      if (this.velocity.y < 0) {
        // 着陆 - 找到准确的地面位置
        this.onGround = true;
        // 找到最高的非空方块位置
        let groundY = Math.floor(newPosition.y);
        for (let y = groundY; y >= groundY - 3; y--) {
          const testPos = { x: newPosition.x, y: y + 1, z: newPosition.z };
          if (!this.isCollidingWithBlocks(testPos, halfWidth, height)) {
            newPosition.y = y + 1;
            break;
          }
        }
      } else {
        // 撞到天花板
        newPosition.y = this.position.y;
      }
      this.velocity.y = 0;
    } else if (hasGroundBelow) {
      // 在地面上但没有碰撞
      this.onGround = true;
      if (this.velocity.y < 0) {
        this.velocity.y = 0;
      }
    } else {
      // 在空中
      this.onGround = false;
    }
    
    // Z轴碰撞检测
    newPosition.z += this.velocity.z * deltaTime;
    if (this.isCollidingWithBlocks(newPosition, halfWidth, height)) {
      newPosition.z = this.position.z;
      this.velocity.z = 0;
    }
    
    return newPosition;
  }

  private isCollidingWithBlocks(position: Vec3, halfWidth: number, height: number): boolean {
    const minX = position.x - halfWidth;
    const maxX = position.x + halfWidth;
    const minY = position.y;
    const maxY = position.y + height;
    const minZ = position.z - halfWidth;
    const maxZ = position.z + halfWidth;
    
    // 检查实体边界框内的所有方块
    for (let x = Math.floor(minX); x <= Math.floor(maxX); x++) {
      for (let y = Math.floor(minY); y <= Math.floor(maxY); y++) {
        for (let z = Math.floor(minZ); z <= Math.floor(maxZ); z++) {
          const blockType = this.worldManager.getBlock({ x, y, z });
          if (blockType > 0) { // 非空气方块
            return true;
          }
        }
      }
    }
    
    return false;
  }

  protected updateMeshPosition(): void {
    if (this.mesh) {
      this.mesh.position.set(this.position.x, this.position.y, this.position.z);
      this.mesh.rotation.y = this.rotation;
    }
  }

  public takeDamage(amount: number): void {
    this.health = Math.max(0, this.health - amount);
    
    // 受伤时的反应
    this.onDamage(amount);
  }

  protected onDamage(amount: number): void {
    // 子类可以重写此方法来实现受伤反应
  }

  protected die(): void {
    if (this.ai) {
      this.ai.state = AIState.DEAD;
    }
    
    // 子类可以重写此方法来实现死亡逻辑
    this.onDeath();
  }

  protected abstract onDeath(): void;

  public getBoundingBox(): BoundingBox {
    const halfWidth = this.stats.size.width / 2;
    const height = this.stats.size.height;
    
    return {
      min: {
        x: this.position.x - halfWidth,
        y: this.position.y,
        z: this.position.z - halfWidth
      },
      max: {
        x: this.position.x + halfWidth,
        y: this.position.y + height,
        z: this.position.z + halfWidth
      }
    };
  }

  public getDistanceTo(target: Vec3): number {
    return Math.sqrt(
      Math.pow(this.position.x - target.x, 2) +
      Math.pow(this.position.y - target.y, 2) +
      Math.pow(this.position.z - target.z, 2)
    );
  }

  public moveTowards(target: Vec3, speed: number): void {
    const direction = {
      x: target.x - this.position.x,
      y: target.y - this.position.y,
      z: target.z - this.position.z
    };
    
    const distance = Math.sqrt(direction.x * direction.x + direction.z * direction.z);
    
    if (distance > 0.1) {
      direction.x /= distance;
      direction.z /= distance;
      
      this.velocity.x = direction.x * speed;
      this.velocity.z = direction.z * speed;
      
      // 更新朝向
      this.rotation = Math.atan2(direction.x, direction.z);
    }
  }

  // Getters
  public getId(): string { return this.id; }
  public getType(): EntityType { return this.type; }
  public getPosition(): Vec3 { return { ...this.position }; }
  public getVelocity(): Vec3 { return { ...this.velocity }; }
  public getRotation(): number { return this.rotation; }
  public getHealth(): number { return this.health; }
  public getMaxHealth(): number { return this.maxHealth; }
  public isAlive(): boolean { return this.health > 0; }
  public getMesh(): THREE.Object3D | undefined { return this.mesh; }
  public getStats(): EntityStats { return this.stats; }
  public getAI(): AIBehavior | undefined { return this.ai; }

  // Setters
  public setPosition(position: Vec3): void {
    this.position = { ...position };
  }

  public setVelocity(velocity: Vec3): void {
    this.velocity = { ...velocity };
  }

  public setRotation(rotation: number): void {
    this.rotation = rotation;
  }

  public getData(): EntityData {
    return {
      id: this.id,
      type: this.type,
      position: this.position,
      rotation: this.rotation,
      health: this.health,
      maxHealth: this.maxHealth,
      velocity: this.velocity,
      onGround: this.onGround,
      age: this.age
    };
  }

  public dispose(): void {
    if (this.mesh) {
      // 清理网格资源
      if (this.mesh.parent) {
        this.mesh.parent.remove(this.mesh);
      }
      
      // 清理几何体和材质
      this.mesh.traverse((child) => {
        if (child instanceof THREE.Mesh) {
          if (child.geometry) {
            child.geometry.dispose();
          }
          if (child.material) {
            if (Array.isArray(child.material)) {
              child.material.forEach(mat => mat.dispose());
            } else {
              child.material.dispose();
            }
          }
        }
      });
    }
  }
}